package com.ruoyi.web.controller.system;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.constant.IAMConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.IAMException;
import com.ruoyi.framework.shiro.util.SignBuilder;
import com.ruoyi.framework.shiro.util.secret.MD5Util;
import com.ruoyi.framework.shiro.util.secret.SecurityUtil;
import com.ruoyi.framework.web.service.SyncService;
import com.ruoyi.system.domain.SysThird;
import com.ruoyi.system.domain.sync.*;
import com.ruoyi.system.service.ISysThirdService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author renzhihao
 * @date 2023/12/08 16:13
 */
@RestController
@RequestMapping("/sync")
public class AppDataSyncController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(AppDataSyncController.class);

    @Autowired
    private ISysThirdService thirdService;

    @Autowired
    private SyncService syncService;

    @PostMapping("account")
    public AjaxResult syncUserDept(@RequestBody SyncUserDeptData syncUserDeptData, HttpServletRequest request) {
        log.info("接收到应用组织/账号同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();

        syncUserDept(syncUserDeptData, method, servletPath);
        return iamSuccess(syncUserDeptData.getSign());
    }

    @PostMapping("user")
    public AjaxResult syncUser(@RequestBody SyncUserDeptData syncUserDeptData, HttpServletRequest request) {
        log.info("接收到应用账号同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();

        syncUserDept(syncUserDeptData, method, servletPath);
        return iamSuccess(syncUserDeptData.getSign());
    }

    @PostMapping("dept")
    public AjaxResult syncDept(@RequestBody SyncUserDeptData syncUserDeptData, HttpServletRequest request) {
        log.info("接收到应用组织同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();

        syncUserDept(syncUserDeptData, method, servletPath);
        return iamSuccess(syncUserDeptData.getSign());
    }


    @PostMapping
    public AjaxResult sync(@RequestBody SyncAppData syncAppData, HttpServletRequest request) {
        log.info("接收到二级权限同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        sync(syncAppData, method, servletPath);

        return iamSuccess();
    }

    @PostMapping("role")
    public AjaxResult syncRole(@RequestBody SyncAppData syncAppData, HttpServletRequest request) {
        log.info("接收到角色同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        sync(syncAppData, method, servletPath);

        return iamSuccess();
    }

    @PostMapping("permission")
    public AjaxResult syncPermission(@RequestBody SyncAppData syncAppData, HttpServletRequest request) {
        log.info("接收到权限同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        sync(syncAppData, method, servletPath);

        return iamSuccess();
    }

    @PostMapping("rolePermission")
    public AjaxResult syncRolePermission(@RequestBody SyncAppData syncAppData, HttpServletRequest request) {
        log.info("接收到角色权限关联关系同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        sync(syncAppData, method, servletPath);

        return iamSuccess();
    }

    @PostMapping("permissionAccount")
    public AjaxResult syncPermissionAccount(@RequestBody SyncAppData syncAppData, HttpServletRequest request) {
        log.info("接收到权限账号关联关系同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        sync(syncAppData, method, servletPath);

        return iamSuccess();
    }

    @PostMapping("roleAccount")
    public AjaxResult syncRoleAccount(@RequestBody SyncAppData syncAppData, HttpServletRequest request) {
        log.info("接收到角色账号关联关系同步请求");
        String method = request.getMethod();
        String servletPath = request.getServletPath();
        sync(syncAppData, method, servletPath);

        return iamSuccess();
    }

    private void sync(SyncAppData syncAppData, String method, String path) {
        SysThird third = thirdService.selectThirdAuth();
        String key = third.getDataKey();
        log.info("当前数据类型：{}", syncAppData.getDataType());
        String data = SecurityUtil.decryptAES(syncAppData.getData(), key);
        log.info("数据原文：{}", data);

        String sign = SignBuilder.create(syncAppData.getClientId(), key)
                .requestPath(path)
                .requestMethod(method.toUpperCase())
                .param("timestamp", syncAppData.getTimestamp())
                .param("dataType", syncAppData.getDataType())
                .salt(syncAppData.getSalt())
                .sign();

        Map<String, String> map = JSONUtil.toBean(data, new TypeReference<>() {
        }, true);

        if (!StringUtils.equalsIgnoreCase(map.get("sign"), sign)) {
            throw new IAMException("签名校验失败");
        }


        if (!StringUtils.equalsIgnoreCase(sign, syncAppData.getSign())) {
            throw new IAMException("签名校验失败");
        }

        String syncData = map.get("syncData");
        if (Objects.equals(syncAppData.getDataType(), IAMConstants.SYNC_PERMISSION)) {
            List<IAMPermission> iamPermissionList = JSONUtil.toList(syncData, IAMPermission.class);
            syncService.syncPermission(iamPermissionList);
            return;
        }

        if (Objects.equals(syncAppData.getDataType(), IAMConstants.SYNC_ROLE)) {
            List<IAMRole> iamRoleList = JSONUtil.toList(syncData, IAMRole.class);
            syncService.syncRole(iamRoleList);
            return;
        }

        if (Objects.equals(syncAppData.getDataType(), IAMConstants.SYNC_ROLE_PERMISSION)) {
            List<IAMRolePermission> iamRolePermissionList = JSONUtil.toList(syncData, IAMRolePermission.class);
            syncService.syncRolePermission(iamRolePermissionList);
            return;
        }

        if (Objects.equals(syncAppData.getDataType(), IAMConstants.SYNC_ROLE_ACCOUNT)) {
            List<IAMRoleAccount> iamRoleAccountList = JSONUtil.toList(syncData, IAMRoleAccount.class);
            syncService.syncRoleAccount(iamRoleAccountList);
            return;
        }

        if (Objects.equals(syncAppData.getDataType(), IAMConstants.SYNC_PERMISSION_ACCOUNT)) {
            List<IAMPermissionAccount> iamPermissionAccountList = JSONUtil.toList(syncData, IAMPermissionAccount.class);
            syncService.syncPermissionAccount(iamPermissionAccountList);
        }

    }


    private void syncUserDept(SyncUserDeptData syncUserDeptData, String method, String path) {
        SysThird third = thirdService.selectThirdAuth();

        String secret = MD5Util.getMD5String(third.getAppSecret());
        log.info("当前数据类型：{}", syncUserDeptData.getDataType());
        String data = SecurityUtil.decryptAES(syncUserDeptData.getSyncData(), secret);
        log.info("数据原文：{}", data);

        String sign = SignBuilder.create(third.getAppId(), secret)
                .requestPath(path)
                .requestMethod(method.toUpperCase())
                .param("timestamp", syncUserDeptData.getTimestamp())
//                .param("dataType", syncUserDeptData.getDataType())
                .salt(syncUserDeptData.getSalt())
                .sign();

        if (!StringUtils.equalsIgnoreCase(sign, syncUserDeptData.getSign())) {
            throw new IAMException("签名校验失败");
        }

        if (Objects.equals(syncUserDeptData.getDataType(), IAMConstants.SYNC_DEPT)) {
            List<IAMSyncDept> iamSyncDeptList = JSONUtil.toList(data, IAMSyncDept.class);
            syncService.syncDept(iamSyncDeptList);
        } else if (Objects.equals(syncUserDeptData.getDataType(), IAMConstants.SYNC_ACCOUNT)) {
            List<IAMSyncAccount> iamSyncAccountList = JSONUtil.toList(data, IAMSyncAccount.class);
            syncService.syncUser(iamSyncAccountList);
        }
    }
}
